﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using DDD;
using FloatComparer = UnitTest.TestHelper.FloatComparer;

namespace UnitTest.TestFeedback {
    [TestClass]
    public class TestFeedback_float_vec2_vec3_vec4_ {

        #region Field
        GameWindow window;
        World wld;
        Graphics3D g3d;
        FeedbackBuffer fbuf;
        #endregion

        #region Setup
        [TestInitialize ()]
        public void MyClassInitialize () {
            window = new GameWindow ();
            wld = CreateWorld ();
            var fbuf = CreateFrameBuffer ();

            g3d = Graphics3D.GetInstance ();
            g3d.Reset ();

            g3d.RenderPass += delegate {
                g3d.SetFrameBuffer (fbuf);
                g3d.SetWorld (wld);
                g3d.SetViewort (0, 0, 1, 1);
            };
        }

        [TestCleanup ()]
        public void MyClassCleanup () {
            window.Dispose ();
            window = null;
            wld = null;
        }

        private static FrameBuffer CreateFrameBuffer () {
            // (0,0,0)だと駄目か？
            var fbuf = new FrameBuffer (1, 1, 0);
            var color0 = new Image2D<float> (DDD.PixelFormat.RGBA8, 1, 1);
            fbuf.SetColorBuffer (0, color0);
            return fbuf;
        }


        private World CreateWorld () {
            var cam = new Camera ();
            cam.SetPerspective (45, 1, 0.1f, 10f);

            var camNode = new Node ();
            camNode.Attach (cam);
            camNode.SetTranslation (0, 0, 1);

            var pos = new float[3] { 0, 0, 0 };
            var col = new float[4] { 1, 2, 3, 4 };
            var posArray = new VertexArray<float> (1, 3);
            var colArray = new VertexArray<float> (1, 4);
            posArray.Set (0, 1, pos);
            colArray.Set (0, 1, col);

            var vbuf = new VertexBuffer ();
            vbuf.AddVertexArray ("v_Position", posArray);
            vbuf.AddVertexArray ("v_Color", colArray);

            var fbArray = new VertexArray<float> (1, 4);

            var fbuf = new FeedbackBuffer ();
            fbuf.AddVertexArray ("f_Color", fbArray);

            var vert = @"#version 400
                         in  vec3 v_Position;
                         in  vec4 v_Color;
                         out vec4 f_Color;
                         
                         void main () {
                             gl_Position = vec4(v_Position, 1);
                             f_Color = v_Color;
                         }
                        ";
            var frag = @"#version 400
                         in vec4 f_Color;
                         out vec4 frag_Color;

                         void main () {
                             frag_Color = f_Color;
                         }
                        ";
            //var vs = new VertexShader (new MemoryStream (Encoding.UTF8.GetBytes (vert)));
            //var fs = new FragmentShader (new MemoryStream (Encoding.UTF8.GetBytes (frag)));
            var vs = new VertexShader (@"C:\Users\ueda\Dev\Workspace.DDD\DokiDokiDynamo\UnitTest\transform.vert");
            var fs = new FragmentShader (@"C:\Users\ueda\Dev\Workspace.DDD\DokiDokiDynamo\UnitTest\transform.frag");
            var sp = new ShaderProgram (vs, fs);
            sp.SetTransformFeedbackEnable (true, 1); // 自動でいいよな？
            sp.SetFeedbackVarying (0, "f_Color");

            var app = new Appearance ();
            app.SetShaderProgram (sp);

            var msh = new Transformer ();
            msh.SetVertexBuffer (vbuf);
            msh.SetFeedbackBuffer (fbuf);
            msh.SetAppearance (app);

            var mshNode = new Node ();
            mshNode.Attach (msh);

            var wld = new World ();
            wld.AddChild (camNode);
            wld.AddChild (mshNode);
            wld.SetActiveCamera (camNode);

            return wld;
        }

        #endregion



        #region TestMethod
        [TestMethod]
        public void TestMethod1 () {

            g3d.Render ();
            window.SwapBuffers ();

            var expected0 = new float[4] { 1,2,3,4 };
            var colors0 = new float[4];
            
            var color0 = fbuf.GetVertexArray("f_Color") as VertexArray<float>;
            color0.Capture ();
            color0.Get (0,  1, colors0);

            CollectionAssert.AreEqual (expected0, colors0, new FloatComparer (0.01f));
        }
        #endregion



    }
}
